using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Script.Serialization;
using NUnit.Framework;

namespace DeeplyNestedJson
{
    [TestFixture]
    public class JsonTests
    {
        private readonly string _json = "{\"Int\":1,\"Decimal\":1.0,\"String\":\"Number 1\",\"List\":[{\"Int\":2,\"Decimal\":2.0,\"String\":\"Number 2\",\"List\":[]},{\"Int\":3,\"Decimal\":3.0,\"String\":\"Number 3\",\"List\":[]},{\"Int\":4,\"Decimal\":4.0,\"String\":\"Number 4\",\"List\":[{\"Int\":5,\"Decimal\":5.0,\"String\":\"Number 5\",\"List\":[]},{\"Int\":6,\"Decimal\":6.0,\"String\":\"Number 6\",\"List\":[]}]}]}";

        [Test]
        public void Can_serialize_deeply_nested_objects()
        {
            Assert.AreEqual(_json, new JavaScriptSerializer().Serialize(GetSample()));
        }

        [Test]
        public void Can_deserialize_deeply_nested_objects()
        {
            var sample = new JavaScriptSerializer().Deserialize<Sample>(_json);

            Assert.AreEqual(1, sample.Int);
            Assert.AreEqual(1.0m, sample.Decimal);
            Assert.AreEqual("Number 1", sample.String);
            Assert.AreEqual(3, sample.List.Count);

            Assert.AreEqual(2, sample.List[2].List.Count);
            Assert.AreEqual(5, sample.List[2].List[0].Int);
            Assert.AreEqual(5.0m, sample.List[2].List[0].Decimal);
            Assert.AreEqual("Number 5", sample.List[2].List[0].String);
        }

        private Sample GetSample()
        {
            return new Sample(1, new[]
                {
                    new Sample(2),
                    new Sample(3),
                    new Sample(4, new[]
                        {
                            new Sample(5),
                            new Sample(6),
                        }),
                });
        }

        public class Sample
        {
            public Sample()
            {
            }

            public Sample(int i, IEnumerable<Sample> list = null)
            {
                Int = i;
                Decimal = 1.0m * i;
                String = "Number " + i;
                List = (list ?? Enumerable.Empty<Sample>()).ToList();
            }

            public int Int { get; set; }
            public decimal Decimal { get; set; }
            public string String { get; set; }
            public IList<Sample> List { get; set; }
        }
    }
}